package kr.pe.johnkim.carrotpoint.mobile.controller;

import kr.pe.johnkim.carrotpoint.mobile.domain.CarrotPointCertification;
import kr.pe.johnkim.carrotpoint.mobile.service.CarrotPointCertificationService;
import kr.pe.johnkim.carrotpoint.mobile.util.CarrotPointCommon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * Carrot Point 인증 관련 controller 클래스 이다.
 *
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 2. 6.
 */
@Controller
@RequestMapping(value = "/carrotPointCertificationController")
public class CarrotPointCertificationController {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(CarrotPointCertificationController.class);

    @Autowired
    private CarrotPointCertificationService carrotPointCertificationService;

    @Autowired
    private CarrotPointCommon carrotPointCommon;

    @Autowired
    private TaskExecutor taskExecutor;

    // 인증 허가 요청 메소드 호출 여부.
    private boolean REQUEST_PERMISSION;

    // taskExecutor 실행 횟수 확인.
    private int REQUEST_INTERVAL = 0;

    /**
     * 해당 사용자가 인증 번호를 요청 한다.
     *
     * 1. 인증 번호 생성.
     * 2. 생성한 인증번호를 database 에 저장.
     * 3. 생성한 인증번호를 해당 사용자에게 SMS 로 전송.
     *
     * @param carrotPointCertification
     * @throws Exception
     */
    @RequestMapping(value = "/requestCertification", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointCertification requestCertification
            (@RequestBody final CarrotPointCertification carrotPointCertification) throws Exception {
        logger.info("requestCertification");

        /*
        사용자가 인증번호 요청버튼을 연속으로 누를 수도 있기때문에
        기존에 요청한 정보가 있는지 확인하고 있으면 비활성화 시킨 후 다시 인증번호를 송신 한다.
         */
        try {
            // 만약 기존에 요청한 인증정보가 있다면,
            if(("1").equals(this.carrotPointCertificationService.getExistCertificationInformation(carrotPointCertification).getTotalCount())) {
                // 저장된 사용자의 인증 정보를 가져 온다.
                CarrotPointCertification resultCertification = this.carrotPointCertificationService.getCertificationInformation(carrotPointCertification);

                String idCarrotPointCertification = resultCertification.getIdCarrotPointCertification();

                logger.info("phone number          : {}", carrotPointCertification.getPhoneNumber());

                // 기존 인증번호를 비활성화 한다.
                CarrotPointCertification parameter = new CarrotPointCertification();

                parameter.setIdCarrotPointCertification(idCarrotPointCertification);
                parameter.setActivateYn("N");
                parameter.setModifyDate(this.carrotPointCommon.getCurrentDate());

                this.carrotPointCertificationService.updateDeactivateCertification(parameter);
            }
        } catch (Exception e) {
            logger.error("error occurred while deactivate user certification.");
        }

        REQUEST_PERMISSION = true;

        // 4자리의 인증번호를 생성 한다.
        String certificationNumber = String.valueOf(carrotPointCommon.getCertificationNumber());

        CarrotPointCertification parameter = new CarrotPointCertification();
        parameter.setCertificationNumber(certificationNumber);
        carrotPointCertification.setCertificationNumber(parameter.getCertificationNumber());

        logger.info("phone number         : {}", carrotPointCertification.getPhoneNumber());
        logger.info("certification number : {}", carrotPointCertification.getCertificationNumber());
        logger.info("activate yn          : {}", carrotPointCertification.getActivateYn());
        logger.info("modify date          : {}", carrotPointCertification.getModifyDate());
        logger.info("register date        : {}", carrotPointCertification.getRegisterDate());

        final CarrotPointCertification result = new CarrotPointCertification();

        try {
            // 사용자 정보와 인증번호를 저장 한다.
            this.carrotPointCertificationService.registerCertification(carrotPointCertification);

            /*
            호스팅 업체에서 제공 받은 SMS 전송 로직 삽입해야 함.
            인증번호 전송.
             */

            result.setResult("SUCCESS");
        } catch (Exception e) {
            result.setResult("FAIL");
        }

        /*
        thread 가 돌면서 5분안에 requestPermission 메소드가 호출되는지 확인한다.
        만약 호출되지 않으면 기존 인증번호를 비활성화 하고 새로운 인증번호를 요청하라는 Push Notification 을 발송 한다.
         */
        taskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                logger.info("taskExecutor start : {}", carrotPointCertification.getPhoneNumber());

                // 1초에 한번씩 REQUEST_PERMISSION 이 false 로 업데이트 되었는지 확인 한다.
                while (true) {
                    try {
                        Thread.sleep(1000);
                        REQUEST_INTERVAL++;
                    } catch (InterruptedException e) {
                        logger.error("error occurred on taskExecutor.");
                    }

                    // Thread 는 5분간 작동하면서 requestPermission 메소드가 호출되었는지 확인 한다.
                    if(REQUEST_INTERVAL != 300) {
                        // 만약 requestPermission 메소드가 호출되었으면 thread 를 종료 한다.
                        if(!REQUEST_PERMISSION) {
                            logger.info("taskExecutor stop.");

                            // taskExecutor 실행 횟수 확인 초기화.
                            REQUEST_INTERVAL = 0;

                            break;
                        }
                    } else {
                        // 만약 5분내에 requestPermission 메소드가 호출되지 않으면 인증 요청을 취소하고 사용자에게 Push Notification 을 전송 한다.
                        if(REQUEST_PERMISSION) {
                            REQUEST_PERMISSION = false;

                            // 기존 인증번호를 비활성화 한다.
                            // 저장된 사용자의 인증 정보를 가져 온다.
                            CarrotPointCertification resultCertification = carrotPointCertificationService.getCertificationInformation(carrotPointCertification);

                            String idCarrotPointCertification = resultCertification.getIdCarrotPointCertification();
                            CarrotPointCertification parameter = new CarrotPointCertification();

                            parameter.setIdCarrotPointCertification(idCarrotPointCertification);
                            parameter.setActivateYn("N");
                            parameter.setModifyDate(carrotPointCommon.getCurrentDate());

                            logger.info("idCarrotPointCertification : {}", parameter.getIdCarrotPointCertification());
                            logger.info("activateYn                 : {}", parameter.getActivateYn());
                            logger.info("modifyDate                 : {}", parameter.getModifyDate());

                            carrotPointCertificationService.updateDeactivateCertification(parameter);

                            logger.info("taskExecutor stop.");

                            /*
                            호스팅 업체에서 제공 받은 SMS 전송 로직 삽입해야 함.
                            시간초과. 다시 인증번호 요청하세요.
                             */

                            // taskExecutor 실행 횟수 확인 초기화.
                            REQUEST_INTERVAL = 0;

                            break;
                        }
                    }
                }
            }
        });

        return result;
    }

    /**
     * 해당 사용자가 SMS 로 받은 인증번호를 보내서 인증 허가를 요청 한다.
     *
     * 1. database 에 저장되어 있는 인증 정보와 비교 한다.
     * 2. 결과를 반환해서 인증 프로세스를 마친다.
     *
     * @param carrotPointCertification
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/requestPermission", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointCertification requestPermission
            (@RequestBody CarrotPointCertification carrotPointCertification) throws Exception {
        logger.info("requestPermission");

        CarrotPointCertification result = new CarrotPointCertification();

        try {
            REQUEST_PERMISSION = false;

            // 저장된 사용자의 인증 정보가 있는지 확인 한다.
            if(("1").equals(this.carrotPointCertificationService.getExistCertificationInformation(carrotPointCertification).getTotalCount())) {

                // 저장된 사용자의 인증 정보를 가져 온다.
                CarrotPointCertification resultCertification = this.carrotPointCertificationService.getCertificationInformation(carrotPointCertification);

                String idCarrotPointCertification = resultCertification.getIdCarrotPointCertification();
                String certificationNumber = resultCertification.getCertificationNumber();

                if((certificationNumber).equals(carrotPointCertification.getCertificationNumber())) {

                    logger.info("phone number          : {}", carrotPointCertification.getPhoneNumber());
                    logger.info("certification number1 : {}", carrotPointCertification.getCertificationNumber());
                    logger.info("certification number2 : {}", certificationNumber);

                    logger.info("SUCCESS_PERMISSION");

                    // 로직 성공. 인증번호 일치.
                    result.setResult("SUCCESS_PERMISSION");

                    // 기존 인증번호를 비활성화 한다.
                    CarrotPointCertification parameter = new CarrotPointCertification();

                    parameter.setIdCarrotPointCertification(idCarrotPointCertification);
                    parameter.setActivateYn("N");
                    parameter.setModifyDate(this.carrotPointCommon.getCurrentDate());

                    this.carrotPointCertificationService.updateDeactivateCertification(parameter);
                } else {
                    logger.info("phone number          : {}", carrotPointCertification.getPhoneNumber());
                    logger.info("certification number1 : {}", carrotPointCertification.getCertificationNumber());
                    logger.info("certification number2 : {}", certificationNumber);

                    logger.info("SUCCESS_NON_PERMISSION");

                    // 로직 성공. 인증번호 불일치.
                    result.setResult("SUCCESS_NON_PERMISSION");

                    // 기존 인증번호를 비활성화 한다.
                    CarrotPointCertification parameter = new CarrotPointCertification();

                    parameter.setIdCarrotPointCertification(idCarrotPointCertification);
                    parameter.setActivateYn("N");
                    parameter.setModifyDate(this.carrotPointCommon.getCurrentDate());

                    this.carrotPointCertificationService.updateDeactivateCertification(parameter);
                }
            } else {
                logger.info("SUCCESS_NON_EXIST");

                // 사용자의 저장된 인증 정보가 없다.
                result.setResult("SUCCESS_NON_EXIST");
            }

        } catch (Exception e) {
            logger.error("FAIL");

            // 로직 실패.
            result.setResult("FAIL");
        }

        logger.info("result : {}", result.getResult());

        return result;
    }
}
